#include "xmlmanager.h"
#include <QPen>
#include <QFont>
#include <QColor>
#include <QTextCodec>
XMLManager::XMLManager()
{
	_errMsg = "";
}

void XMLManager::EncodeDisAttribute(DisplayNode *disp, TiXmlElement *ele)
{
    ele->SetDoubleAttribute("width", disp->Width);
    ele->SetDoubleAttribute("height", disp->Height);
    ele->SetDoubleAttribute("cache-offset-x", disp->cacheOffsetX);
    ele->SetDoubleAttribute("cache-offset-y", disp->cacheOffsetY);

    LinkProperty(disp->AxisX, ele);
    LinkProperty(disp->AxisY, ele);
    LinkProperty(disp->ScaleX, ele);
    LinkProperty(disp->ScaleY, ele);
    LinkProperty(disp->PosX, ele);
    LinkProperty(disp->PosY, ele);
    LinkProperty(disp->SkewX, ele);
    LinkProperty(disp->SkewY, ele);
    LinkProperty(disp->Alpha, ele);
    LinkProperty(disp->RotationAngle, ele);
}

void XMLManager::EncodeShpAttribute(ShapeNode * shp, TiXmlElement * ele)
{
	 ele->SetAttribute("shape-count", shp->ShapeCount);
     ele->SetAttribute("shape-id", shp->shapeID);
}

void XMLManager::EncodeShpTool(ShapeNode * shp, TiXmlElement * ele)
{
	TiXmlElement* pen_ele = new TiXmlElement("q-pen");
	pen_ele->SetAttribute("red", shp->LinePen.color().red());
	pen_ele->SetAttribute("green", shp->LinePen.color().green());
	pen_ele->SetAttribute("blue", shp->LinePen.color().blue());
	pen_ele->SetAttribute("alpha", shp->LinePen.color().alpha());
	pen_ele->SetAttribute("width", shp->LinePen.width());
	ele->LinkEndChild(pen_ele);

	TiXmlElement* brush_ele = new TiXmlElement("q-brush");
	TiXmlElement* grdt;
	switch(shp->FillBrush.style())
	{
	case Qt::SolidPattern:
		grdt=new TiXmlElement("solid-color");
		grdt->SetAttribute("red", shp->FillBrush.color().red());
		grdt->SetAttribute("green", shp->FillBrush.color().green());
		grdt->SetAttribute("blue", shp->FillBrush.color().blue());
		grdt->SetAttribute("alpha", shp->FillBrush.color().alpha());
		brush_ele->LinkEndChild(grdt);
		break;
	case Qt::LinearGradientPattern:
	case Qt::RadialGradientPattern:
		grdt = new TiXmlElement("gradient");
		grdt->SetAttribute("type", shp->FillBrush.gradient()->type());
		switch(shp->FillBrush.gradient()->type())
		{
		case QGradient::LinearGradient:
			{
				QLinearGradient* qlg = (QLinearGradient*)(shp->FillBrush.gradient());
				TiXmlElement * start = new TiXmlElement("start");
				start->SetDoubleAttribute("x", qlg->start().x());
				start->SetDoubleAttribute("y", qlg->start().y());
				grdt->LinkEndChild(start);

				TiXmlElement * end = new TiXmlElement("end");
				end->SetDoubleAttribute("x", qlg->finalStop().x());
				end->SetDoubleAttribute("y", qlg->finalStop().y());
				grdt->LinkEndChild(end);
			}
			break;
		case QGradient::RadialGradient:
			{
				QRadialGradient* qrg = (QRadialGradient*)(shp->FillBrush.gradient());

				TiXmlElement * center = new TiXmlElement("center");
				center->SetDoubleAttribute("x", qrg->center().x());
				center->SetDoubleAttribute("y", qrg->center().y());
				center->SetDoubleAttribute("r", qrg->centerRadius());
				grdt->LinkEndChild(center);

				TiXmlElement * focal = new TiXmlElement("focal-point");
				focal->SetDoubleAttribute("x", qrg->focalPoint().x());
				focal->SetDoubleAttribute("y", qrg->focalPoint().y());
				focal->SetDoubleAttribute("r", qrg->focalRadius());
				grdt->LinkEndChild(focal);
			}
			break;
		}
		{
			const QGradient* grpt=shp->FillBrush.gradient();
			QGradientStops stops=grpt->stops();
			for(int i=0;i!=stops.size();++i)
			{
				TiXmlElement *stop=new TiXmlElement("stop");
				stop->SetDoubleAttribute("percentage",stops[i].first);
				stop->SetAttribute("red", stops[i].second.red());
				stop->SetAttribute("green", stops[i].second.green());
				stop->SetAttribute("blue", stops[i].second.blue());
				stop->SetAttribute("alpha", stops[i].second.alpha());
				grdt->LinkEndChild(stop);
			}
			brush_ele->LinkEndChild(grdt);
		}
		break;
	}

	ele->LinkEndChild(brush_ele);
}

void XMLManager::EncodeContAttribute(ContainerNode * cont, TiXmlElement * ele)
{
	 ele->SetAttribute("symbol-count", cont->SymbolCount);
     ele->SetAttribute("symbol-id", cont->symbolID);
}

TiXmlElement* XMLManager::DecodeDisAttribute(DisplayNode *disp, TiXmlElement *ele)
{
    ele->QueryDoubleAttribute("width", &(disp->Width));
    ele->QueryDoubleAttribute("height", &(disp->Height));
    ele->QueryDoubleAttribute("cache-offset-x", &(disp->cacheOffsetX));
    ele->QueryDoubleAttribute("cache-offset-y", &(disp->cacheOffsetY));

    TiXmlElement * p = ele->FirstChildElement();
    disp->AxisX = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->AxisY = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->ScaleX = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->ScaleY = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->PosX = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->PosY = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->SkewX = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->SkewY = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->Alpha = DecodeProNode(p, QString(p->Value()));
    p = p->NextSiblingElement();
    disp->RotationAngle = DecodeProNode(p, QString(p->Value()));

	return p;
}

void XMLManager::DecodeContAttribute(ContainerNode * cont, TiXmlElement * ele)
{
	ele->QueryIntAttribute("symbol-count", &(cont->SymbolCount));
    ele->QueryIntAttribute("symbol-id", &(cont->symbolID));
}

void XMLManager::DecodeShpAttribute(ShapeNode * shp, TiXmlElement * ele)
{
	ele->QueryIntAttribute("shape-count", &(shp->ShapeCount));
    ele->QueryIntAttribute("shape-id", &(shp->shapeID));
}

void XMLManager::DecodeShpTool(ShapeNode * shp, TiXmlElement * p)
{
	int w, pr, pg, pb, pa, br, bg, bb, ba;
    p->QueryIntAttribute("red", &pr);
    p->QueryIntAttribute("green", &pg);
    p->QueryIntAttribute("blue", &pb);
	p->QueryIntAttribute("alpha", &pa);
    p->QueryIntAttribute("width", &w);
    shp->LinePen.setColor(QColor(pr, pg, pb, pa));
    shp->LinePen.setWidth(w);

    p = p->NextSiblingElement();
   
	TiXmlElement * c = p->FirstChildElement("solid-color");
	if(c)
	{
		c->QueryIntAttribute("red", &br);
		c->QueryIntAttribute("green", &bg);
		c->QueryIntAttribute("blue", &bb);
		c->QueryIntAttribute("alpha", &ba);
		shp->FillBrush.setStyle(Qt::SolidPattern);
		shp->FillBrush.setColor(QColor(br, bg, bb, ba));
	}
	else
	{
		c = p->FirstChildElement("gradient");
		if(c)
		{
			int t;//, cm, s;
			QGradient * qg;
			c->QueryIntAttribute("type", &t);
			if ( t == QGradient::LinearGradient)
			{
				c = c->FirstChildElement();
				double x1, y1, x2, y2;
				c->QueryDoubleAttribute("x", &x1);
				c->QueryDoubleAttribute("y", &y1);
				c = c->NextSiblingElement();
				c->QueryDoubleAttribute("x", &x2);
				c->QueryDoubleAttribute("y", &y2);
				qg = new QLinearGradient(x1, y1, x2, y2);
			}
			else if ( t == QGradient::RadialGradient)
			{
				c = c->FirstChildElement();
				double cx, cy, cr, fx, fy, fr;
				c->QueryDoubleAttribute("x", &cx);
				c->QueryDoubleAttribute("y", &cy);
				c->QueryDoubleAttribute("r", &cr);

				c = c->NextSiblingElement();
				c->QueryDoubleAttribute("x", &fx);
				c->QueryDoubleAttribute("y", &fy);
				c->QueryDoubleAttribute("r", &fr);

				qg = new QRadialGradient(cx, cy, cr, fx, fy, fr);
			}
			else
				throw "Not Supported Gradient Type!!";
			c=c->NextSiblingElement();
			while(c)
			{
				double percentage;
				int gr,gg,gb,ga;
				c->QueryDoubleAttribute("percentage",&percentage);
				c->QueryIntAttribute("red",&gr);
				c->QueryIntAttribute("green",&gg);
				c->QueryIntAttribute("blue",&gb);
				c->QueryIntAttribute("alpha",&ga);
				qg->setColorAt(percentage,QColor(gr,gg,gb,ga));
				c=c->NextSiblingElement();
			}
			shp->FillBrush =QBrush(*qg);
		}
		else
			throw "Error Tag";
	}
}

bool XMLManager::LinkSymbol(SymbolNode *root, TiXmlElement *ele, QString path)
{
    try
    {
        TiXmlElement * s_ele = new TiXmlElement("symbol");

		EncodeDisAttribute(root, s_ele);
		EncodeContAttribute(root, s_ele);

        int vectorSize = root->children.size();
        for (int i = 0; i < vectorSize; i ++)
        {
            AtomicNode * an = dynamic_cast<AtomicNode*>(root->children[i]);
            LinkAtomic(an, s_ele, path);
        }

        ele->LinkEndChild(s_ele);
        return true;
    }
    catch (exception e)
    {
        return false;
    }
}

bool XMLManager::LinkAtomic(AtomicNode *root, TiXmlElement *ele, QString path)
{
    try
    {
        PictureNode * pn = dynamic_cast<PictureNode*>(root);
        if (pn)
        {
            QString name = QString::number(pn->pictureID);
            pn->Image.save(path+name+".jpg", "jpg");

            TiXmlElement* pic_ele = new TiXmlElement("picture");

			EncodeDisAttribute(pn, pic_ele);

			pic_ele->SetAttribute("picture-count", pn->PictureCount);
            pic_ele->SetAttribute("picture-id", pn->pictureID);
			
			TiXmlText * ppth = new TiXmlText(pn->Path.toUtf8().data());
            pic_ele->LinkEndChild(ppth);

            ele->LinkEndChild(pic_ele);
        }
        else
        {
            WordShapeNode * wsn = dynamic_cast<WordShapeNode*>(root);
            if (wsn)
            {
                TiXmlElement* w_ele = new TiXmlElement("word-shape");

				EncodeDisAttribute( wsn, w_ele);
				EncodeShpAttribute( wsn, w_ele);
                
				EncodeShpTool( wsn, w_ele);

                TiXmlElement* txt_ele = new TiXmlElement("text");
                TiXmlText* w_txt = new TiXmlText(wsn->text.toUtf8().data());
                txt_ele->LinkEndChild(w_txt);
                w_ele->LinkEndChild(txt_ele);

                TiXmlElement * font = new TiXmlElement("font");

				TiXmlElement * fml = new TiXmlElement("family");				
				fml->LinkEndChild(new TiXmlText(wsn->font.family().toUtf8().data()));
				font->LinkEndChild(fml);

                font->SetAttribute("capitalization", wsn->font.capitalization());
                font->SetAttribute("hinting-preference", wsn->font.hintingPreference());
//                font->SetAttribute("spacing-type", wsn->font);
                font->SetAttribute("stretch", wsn->font.stretch());
                font->SetAttribute("style", wsn->font.style());
                font->SetAttribute("style-hint", wsn->font.styleHint());
                font->SetAttribute("style-strategy", wsn->font.styleStrategy());
                font->SetAttribute("weight", wsn->font.weight());
				font->SetAttribute("size",wsn->font.pointSize());
                w_ele->LinkEndChild(font);

                ele->LinkEndChild(w_ele);
            }
            else
            {
                PathNode * pthn = dynamic_cast<PathNode*>(root);
                RectNode * rn = dynamic_cast<RectNode*>(root);
                if (pthn)
                {
                    TiXmlElement* pth_ele = new TiXmlElement("path");
                    
					EncodeDisAttribute(pthn, pth_ele);
					EncodeShpAttribute(pthn, pth_ele);

                    pth_ele->SetAttribute("is-closed", pthn->isClosed);

					EncodeShpTool(pthn, pth_ele);

                    int pointSize = pthn->points.size();
                    for (int i = 0; i < pointSize; i ++)
                    {
                        TiXmlElement* point_ele = new TiXmlElement("point");
                        point_ele->SetDoubleAttribute("x", pthn->points[i].x());
                        point_ele->SetDoubleAttribute("y", pthn->points[i].y());
                        pth_ele->LinkEndChild(point_ele);
                    }

                    int pttSize = pthn->ptTypes.size();
                    for (int i = 0; i < pttSize; i ++)
                    {
                        TiXmlElement* ptt_ele = new TiXmlElement("pt-type");
                        ptt_ele->SetAttribute("type", pthn->ptTypes[i]);
                        pth_ele->LinkEndChild(ptt_ele);
                    }

                    int ptdSize = pthn->ptDict.size();
                    for ( int i = 0; i < ptdSize; i ++)
                    {
                        TiXmlElement * ptd_ele = new TiXmlElement("pt-dict");
                        ptd_ele->SetAttribute("dict", pthn->ptDict[i]);
                        pth_ele->LinkEndChild(ptd_ele);
                    }

                    ele->LinkEndChild(pth_ele);
                }
                else if (rn)
                {

                    TiXmlElement * re_ele = new TiXmlElement("rect");
                  
					EncodeDisAttribute(rn, re_ele);
					EncodeShpAttribute(rn, re_ele);
					EncodeShpTool(rn, re_ele);

                    ele->LinkEndChild(re_ele);
                }
                else
                {
                    EclipseNode * en = dynamic_cast<EclipseNode*>(root);
                    TiXmlElement * ec_ele = new TiXmlElement("eclipse");
                    EncodeDisAttribute(en, ec_ele);
					EncodeShpAttribute(en, ec_ele);
					EncodeShpTool(en, ec_ele);
  
                    ele->LinkEndChild(ec_ele);
                }

            }
        }

        return true;
    }
    catch (exception e)
    {
        return false;
    }
}

bool XMLManager::LinkProperty(PropertyNode *root, TiXmlElement *ele)
{
    try
    {
        StaticPropertyNode * spn = dynamic_cast<StaticPropertyNode*>(root);
        if (spn)
        {
            TiXmlElement* p_ele = new TiXmlElement("static-property");
            p_ele->SetDoubleAttribute("value", spn->Value);
            ele->LinkEndChild(p_ele);
        }
        else
        {
            AnimatePropertyNode * apn = dynamic_cast<AnimatePropertyNode*>(root);
            TiXmlElement* p_ele = new TiXmlElement("animate-property");
            int tpsize = apn->KeyValues.size();
            for (int i = 0; i < tpsize; i ++)
            {
                TiXmlElement* tp_ele = new TiXmlElement("time-pair");
                tp_ele->SetAttribute("time", apn->KeyValues[i].Time);
                tp_ele->SetDoubleAttribute("value", apn->KeyValues[i].Value);
                p_ele->LinkEndChild(tp_ele);
            }

            int easeSize = apn->ease.size();
            for (int i = 0; i < easeSize; i ++)
            {
                TiXmlElement * ese_ele = new TiXmlElement("ease-type");
                ese_ele->SetAttribute("type", apn->ease[i]);
                p_ele->LinkEndChild(ese_ele);
            }

            ele->LinkEndChild(p_ele);
        }

        return true;
    }
    catch (exception e)
    {
        return false;
    }
}

DisplayNode* XMLManager::DecodeDisNode(TiXmlElement *ele, QString type, QString path)
{

    if (type == "movie-clip")
    {
		MovieClipNode* m=0;
        if (LoadBLK(path+ele->GetText()+"\\", ele->GetText(), m))
			return m;
		else
			return NULL;
    }
    else if (type == "symbol")
    {
        SymbolNode * re_s = new SymbolNode();

		DecodeContAttribute(re_s, ele);
       
        TiXmlElement * p = DecodeDisAttribute(re_s, ele)->NextSiblingElement();
        while (p)
        {
			re_s->children.push_back(DecodeDisNode(p, QString(p->Value()), path));
            p = p->NextSiblingElement();
        }

        return re_s;
    }
    else if(type == "picture")
    {
        PictureNode * re_p = new PictureNode();

		DecodeDisAttribute(re_p, ele);
        ele->QueryIntAttribute("picture-count", &(re_p->PictureCount));
        ele->QueryIntAttribute("picture-id", &(re_p->pictureID));

		re_p->Path = QString(ele->LastChild()->ToText()->Value());

        int id;
        ele->QueryIntAttribute("picture-id", &id);
        re_p->Image.load(path+QString::number(id)+".jpg");

        return re_p;
    }
    else if(type == "rect")
    {
        RectNode * re_r = new RectNode();

		DecodeShpAttribute(re_r, ele);
		TiXmlElement * p = DecodeDisAttribute(re_r, ele)->NextSiblingElement();
		DecodeShpTool(re_r, p);

        return re_r;
    }
    else if ( type == "path")
    {
        PathNode * re_pth = new PathNode();

		ele->QueryBoolAttribute("is-closed", &(re_pth->isClosed));
   
		DecodeShpAttribute(re_pth, ele);
		TiXmlElement * p = DecodeDisAttribute(re_pth, ele)->NextSiblingElement();
		DecodeShpTool(re_pth, p);

        p = p->NextSiblingElement();
        while (p)
        {
            if (QString(p->Value()) == "point")
            {
                int x,y;
                p->QueryIntAttribute("x", &x);
                p->QueryIntAttribute("y", &y);
                QPoint pt(x, y);
                re_pth->points.push_back(pt);
            }
            else if (QString(p->Value()) == "pt-type")
            {
                int t;
                p->QueryIntAttribute("type", &t);
                switch (t)
                {
                case 0:
                    re_pth->ptTypes.push_back(control);
                    break;
                case 1:
                    re_pth->ptTypes.push_back(linear);
                    break;
                case 2:
                    re_pth->ptTypes.push_back(sharp);
                    break;
                case 3:
                    re_pth->ptTypes.push_back(smooth);
                    break;
                case 4:
                    re_pth->ptTypes.push_back(symmetrical);
                    break;
                }
            }
            else
            {
                int d;
                p->QueryIntAttribute("dict", &d);
                re_pth->ptDict.push_back(d);
            }
            p = p->NextSiblingElement();
        }
		re_pth->refresh();
        return re_pth;
    }
    else if (type == "word-shape")
    {
        WordShapeNode * re_w = new WordShapeNode();
   
		DecodeShpAttribute(re_w, ele);
		TiXmlElement * p = DecodeDisAttribute(re_w, ele)->NextSiblingElement();
		DecodeShpTool(re_w, p);

        p = p->NextSiblingElement("text");
		//QTextCodec *codec = QTextCodec::codecForName("GBK");
        re_w->text = QString::fromUtf8(p->GetText());

        p = p->NextSiblingElement();
		TiXmlElement *fml = p->FirstChildElement();
		re_w->font.setFamily(QString::fromUtf8(fml->GetText()));

        int c, h, st, s, sy, sh, ss, wt,si;
        p->QueryIntAttribute("capitalization", &c);
        p->QueryIntAttribute("hinting-preference", &h);
        p->QueryIntAttribute("spacing-type", &st);
        p->QueryIntAttribute("stretch", &s);
        p->QueryIntAttribute("style", &sy);
        p->QueryIntAttribute("style-hint", &sh);
        p->QueryIntAttribute("style-strategy", &ss);
        p->QueryIntAttribute("weight", &wt);
        p->QueryIntAttribute("size", &si);
        re_w->font.setCapitalization((QFont::Capitalization)c);
        re_w->font.setHintingPreference((QFont::HintingPreference)h);
        re_w->font.setStretch((QFont::Stretch)s);
        re_w->font.setStyle((QFont::Style)sy);
        re_w->font.setStyleHint((QFont::StyleHint)sh);
        re_w->font.setStyleStrategy((QFont::StyleStrategy)ss);
        re_w->font.setWeight((QFont::Weight)wt);
		re_w->font.setPointSize(si);

        return re_w;
    }
    else
    {
        EclipseNode * re_en = new EclipseNode();

		DecodeShpAttribute(re_en, ele);
		TiXmlElement * p = DecodeDisAttribute(re_en, ele)->NextSiblingElement();
		DecodeShpTool(re_en, p);

        return re_en;


    }

}

PropertyNode* XMLManager::DecodeProNode(TiXmlElement *ele, QString type)
{
    if (type == "static-property")
    {
        StaticPropertyNode * re_sp = new StaticPropertyNode();
        ele->QueryDoubleAttribute("value", &(re_sp->Value));
        return re_sp;
    }
    else
    {
        AnimatePropertyNode * re_apn = new AnimatePropertyNode();
		TiXmlElement * p = ele->FirstChildElement();
		
        while (p)
        {
            if (QString(p->Value()) == "time-pair")
            {
                int t;
                double v;
				p->QueryIntAttribute("time", &t);
                p->QueryDoubleAttribute("value", &v);
                TimePair *tp = new TimePair(t, v);
                re_apn->KeyValues.push_back(*tp);
            }
			else if (QString(p->Value()) == "ease-type")
            {
                int e;
                p->QueryIntAttribute("type", &e);
                switch (e)
                {
                case 0:
                    re_apn->ease.push_back(Ease::ALLStart);
                    break;
                case 1:
                    re_apn->ease.push_back(Ease::AllEnd);
                    break;
                case 2:
                    re_apn->ease.push_back(Ease::Linear);
                    break;
                case 3:
                    re_apn->ease.push_back(Ease::QuadIn);
                    break;
                case 4:
                    re_apn->ease.push_back(Ease::QuadOut);
                    break;
                case 5:
                    re_apn->ease.push_back(Ease::QuadInOut);
                    break;
                case 6:
                    re_apn->ease.push_back(Ease::CubicIn);
                    break;
                case 7:
                    re_apn->ease.push_back(Ease::CubicOut);
                    break;
                case 8:
                    re_apn->ease.push_back(Ease::CubicInOut);
                    break;
                case 9:
                    re_apn->ease.push_back(Ease::QuartIn);
                    break;
                case 10:
                    re_apn->ease.push_back(Ease::QuartOut);
                    break;
                case 11:
                    re_apn->ease.push_back(Ease::QuartInOut);
                    break;
                case 12:
                    re_apn->ease.push_back(Ease::QuintIn);
                    break;
                case 13:
                    re_apn->ease.push_back(Ease::QuintOut);
                    break;
                case 14:
                    re_apn->ease.push_back(Ease::QuintInOut);
                    break;
                case 15:
                    re_apn->ease.push_back(Ease::SineIn);
                    break;
                case 16:
                    re_apn->ease.push_back(Ease::SineOut);
                    break;
                case 17:
                    re_apn->ease.push_back(Ease::SineInOut);
                    break;
                case 18:
                    re_apn->ease.push_back(Ease::BackIn);
                    break;
                case 19:
                    re_apn->ease.push_back(Ease::BackOut);
                    break;
                case 20:
                    re_apn->ease.push_back(Ease::BackInOut);
                    break;
                case 21:
                    re_apn->ease.push_back(Ease::CircIn);
                    break;
                case 22:
                    re_apn->ease.push_back(Ease::CircOut);
                    break;
                case 23:
                    re_apn->ease.push_back(Ease::CircInOut);
                    break;
                case 24:
                    re_apn->ease.push_back(Ease::BounceIn);
                    break;
                case 25:
                    re_apn->ease.push_back(Ease::BounceOut);
                    break;
                case 26:
                    re_apn->ease.push_back(Ease::BounceInOut);
                    break;
                case 27:
                    re_apn->ease.push_back(Ease::ElasticIn);
                    break;
                case 28:
                    re_apn->ease.push_back(Ease::ElasticOut);
                    break;
                case 29:
                    re_apn->ease.push_back(Ease::ElasticInOut);
                    break;
                }
            }
            p = p->NextSiblingElement();
        }

        return re_apn;
    }
}

bool XMLManager::OutputXML(QString name, QString path, ContainerNode *root)
{
    try
    {
        TiXmlDocument doc;
        TiXmlDeclaration * decl = new TiXmlDeclaration("1.0","","");

        doc.LinkEndChild(decl);

        TiXmlElement* ele;

        SymbolNode * sybl = dynamic_cast<SymbolNode*>(root);
        if (sybl)
        {
             ele = new TiXmlElement("symbol");
        }
        else
        {
            ele = new TiXmlElement("movie-clip");
            ele->SetAttribute("is-loop", dynamic_cast<MovieClipNode*>(root)->IsLoop);
        }
        ele->SetDoubleAttribute("width", root->GetWidth());
        ele->SetDoubleAttribute("height", root->GetHeight());
        ele->SetDoubleAttribute("cache-offset-x", root->CacheOffsetX());
        ele->SetDoubleAttribute("cache-offset-y", root->CacheOffsetY());
        ele->SetAttribute("symbol-count", root->SymbolCount);
        ele->SetAttribute("symbol-id", root->symbolID);

        LinkProperty(root->AxisX, ele);
        LinkProperty(root->AxisY, ele);
        LinkProperty(root->ScaleX, ele);
        LinkProperty(root->ScaleY, ele);
        LinkProperty(root->PosX, ele);
        LinkProperty(root->PosY, ele);
        LinkProperty(root->SkewX, ele);
        LinkProperty(root->SkewY, ele);
        LinkProperty(root->Alpha, ele);
        LinkProperty(root->RotationAngle, ele);
        LinkProperty(root->Visible, ele);

        int vectorSize = root->children.size();
        for (int i = 0; i < vectorSize; i ++)
        {
            if (root->ChildrenAt(i)->IsAtomic())
            {
                LinkAtomic(dynamic_cast<AtomicNode*>(root->ChildrenAt(i)), ele, path);
            }
            else
            {
                SymbolNode * sn = dynamic_cast<SymbolNode*>(root->ChildrenAt(i));
                if (sn)
                {
                    LinkSymbol(sn, ele, path);
                }
                else
                {
                    DirManager * dm = new DirManager();
                    QString folderName = QString::number(i);
                    dm->CreateFolder(path, folderName);
					OutputXML(folderName ,path+folderName+"\\",dynamic_cast<ContainerNode*>(root->children[i]));
                    TiXmlElement * m = new TiXmlElement("movie-clip");
                    TiXmlText * t = new TiXmlText(folderName.toUtf8().data());
                    m->LinkEndChild(t);
                    ele->LinkEndChild(m);
                }
            }
        }

        doc.LinkEndChild(ele);

        QString file_path = path + name + ".blk";
        doc.SaveFile(file_path.toUtf8().data());

        return true;
    }
    catch (exception e)
    {
		_errMsg = QString(e.what());
        return false;
    }

}

bool XMLManager::OutputXML(QString name, QString path, ContainerNode *root, SceneNode *scene)
{
    try
    {
        TiXmlDocument doc;
        TiXmlDeclaration * decl = new TiXmlDeclaration("1.0","","");

        doc.LinkEndChild(decl);

        TiXmlElement * pj = new TiXmlElement("project");

        TiXmlElement * sc_ele = new TiXmlElement("scene");
		TiXmlElement * sname = new TiXmlElement("name");
		TiXmlText * ntxt = new TiXmlText(scene->name.toUtf8().data());
		sname->LinkEndChild(ntxt);
		sc_ele->LinkEndChild(sname);
        sc_ele->SetAttribute("duration-time", scene->DurationTime);
        sc_ele->SetAttribute("width", scene->Width);
        sc_ele->SetAttribute("height", scene->Height);
        sc_ele->SetAttribute("fps", scene->FPS);

        TiXmlElement * bgcolor = new TiXmlElement("background-color");
        bgcolor->SetAttribute("red", scene->BackgroundColor.red());
        bgcolor->SetAttribute("green", scene->BackgroundColor.green());
        bgcolor->SetAttribute("blue", scene->BackgroundColor.blue());
        bgcolor->SetAttribute("alpha", scene->BackgroundColor.alpha());

        sc_ele->LinkEndChild(bgcolor);

        TiXmlElement* ele;

        SymbolNode * sybl = dynamic_cast<SymbolNode*>(root);
        if (sybl)
        {
             ele = new TiXmlElement("symbol");
        }
        else
        {
            ele = new TiXmlElement("movie-clip");
            ele->SetAttribute("is-loop", dynamic_cast<MovieClipNode*>(root)->IsLoop);
        }

        ele->SetDoubleAttribute("width", root->GetWidth());
        ele->SetDoubleAttribute("height", root->GetHeight());
        ele->SetDoubleAttribute("cache-offset-x", root->CacheOffsetX());
        ele->SetDoubleAttribute("cache-offset-y", root->CacheOffsetY());
        ele->SetAttribute("symbol-count", root->SymbolCount);
        ele->SetAttribute("symbol-id", root->symbolID);

        LinkProperty(root->AxisX, ele);
        LinkProperty(root->AxisY, ele);
        LinkProperty(root->ScaleX, ele);
        LinkProperty(root->ScaleY, ele);
        LinkProperty(root->PosX, ele);
        LinkProperty(root->PosY, ele);
        LinkProperty(root->SkewX, ele);
        LinkProperty(root->SkewY, ele);
        LinkProperty(root->Alpha, ele);
        LinkProperty(root->RotationAngle, ele);
        LinkProperty(root->Visible, ele);

        int vectorSize = root->children.size();
        for (int i = 0; i < vectorSize; i ++)
        {
            if (root->ChildrenAt(i)->IsAtomic())
            {
                LinkAtomic(dynamic_cast<AtomicNode*>(root->ChildrenAt(i)), ele, path);
            }
            else
            {
                SymbolNode * sn = dynamic_cast<SymbolNode*>(root->ChildrenAt(i));
                if (sn)
                {
                    LinkSymbol(sn, ele, path);
                }
                else
                {
                    DirManager * dm = new DirManager();
                    QString folderName = QString::number(i);
                    dm->CreateFolder(path, folderName);
                    OutputXML(folderName ,path+folderName+"\\",dynamic_cast<ContainerNode*>(root->children[i]));
                    TiXmlElement * m = new TiXmlElement("movie-clip");
                    TiXmlText * t = new TiXmlText(folderName.toUtf8().data());
                    m->LinkEndChild(t);
                    ele->LinkEndChild(m);
                }
            }
        }

        pj->LinkEndChild(sc_ele);
        pj->LinkEndChild(ele);
        doc.LinkEndChild(pj);

        QString file_path = path + name + ".cbp";
        doc.SaveFile(file_path.toUtf8().data());

        return true;
    }
    catch (exception e)
    {
		_errMsg = QString(e.what());
        return false;
    }
}

bool XMLManager::LoadBLK(QString path, QString name, MovieClipNode*& movie)
{
    try
    {
        MovieClipNode * re_m = new MovieClipNode();
        TiXmlDocument doc((path+name+".blk").toUtf8().data());
        bool loadOK = doc.LoadFile();
        if (!loadOK)
		{
			_errMsg = "cannot load the .blk file!";
            return false;
		}

        TiXmlHandle hDoc(&doc);
        TiXmlElement * pElem;
        TiXmlHandle hRoot(0);

        pElem = doc.RootElement();
        hRoot = TiXmlHandle(pElem);

        pElem->QueryBoolAttribute("is-loop", &(re_m->IsLoop));
        pElem->QueryDoubleAttribute("width", &(re_m->Width));
        pElem->QueryDoubleAttribute("height", &(re_m->Height));
        pElem->QueryDoubleAttribute("cache-offset-x", &(re_m->cacheOffsetX));
        pElem->QueryDoubleAttribute("cache-offset-y", &(re_m->cacheOffsetY));
        pElem->QueryIntAttribute("symbol-count", &(re_m->SymbolCount));
        pElem->QueryIntAttribute("symbol-id", &(re_m->symbolID));

        pElem = pElem->FirstChildElement();
        re_m->AxisX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->AxisY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->ScaleX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->ScaleY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->PosX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->PosY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->SkewX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->SkewY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->Alpha = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->RotationAngle = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->Visible = DecodeProNode(pElem, QString(pElem->Value()));

        pElem = pElem->NextSiblingElement();
        while (pElem)
        {
			DisplayNode* d = DecodeDisNode(pElem, QString(pElem->Value()), path);
			if ( d != NULL)
				re_m->children.push_back(d);
			else
				return false;
            pElem = pElem->NextSiblingElement();
        }

        movie = re_m;
		
		return true;

    }
    catch (exception e)
    {
		_errMsg = QString(e.what());
        return false;
    }
}

bool XMLManager::LoadCBP(QString path, QString name, MovieClipNode*& movie, SceneNode*& scene)
{
    try
    {
        SceneNode * re_s = new SceneNode();
        MovieClipNode * re_m = new MovieClipNode();
        TiXmlDocument doc((path+name+".cbp").toUtf8().data());
        bool loadOK = doc.LoadFile();
        if (!loadOK)
		{
			_errMsg = "Cannot load the .cbp file!";
            return false;
		}

        TiXmlHandle hDoc(&doc);
        TiXmlElement * pElem;
        TiXmlHandle hRoot(0);

        pElem = doc.RootElement();
        hRoot = TiXmlHandle(pElem);

        pElem = pElem->FirstChildElement();
		TiXmlElement * n = pElem->FirstChildElement();
		re_s->name = QString(n->GetText());

        pElem->QueryIntAttribute("duration-time", &(re_s->DurationTime));
        pElem->QueryIntAttribute("width", &(re_s->Width));
        pElem->QueryIntAttribute("height", &(re_s->Height));
        pElem->QueryIntAttribute("fps", &(re_s->FPS));
        TiXmlElement * pc = n->NextSiblingElement();
        int r,g,b,a;
        pc->QueryIntAttribute("red", &r);
        pc->QueryIntAttribute("green", &g);
        pc->QueryIntAttribute("blue", &b);
        pc->QueryIntAttribute("alpha", &a);
        re_s->BackgroundColor=QColor(r,g,b,a);

        pElem = pElem->NextSiblingElement();

        pElem->QueryBoolAttribute("is-loop", &(re_m->IsLoop));
        pElem->QueryDoubleAttribute("width", &(re_m->Width));
        pElem->QueryDoubleAttribute("height", &(re_m->Height));
        pElem->QueryDoubleAttribute("cache-offset-x", &(re_m->cacheOffsetX));
        pElem->QueryDoubleAttribute("cache-offset-y", &(re_m->cacheOffsetY));
        pElem->QueryIntAttribute("symbol-count", &(re_m->SymbolCount));
        pElem->QueryIntAttribute("symbol-id", &(re_m->symbolID));

        pElem = pElem->FirstChildElement();
        re_m->AxisX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->AxisY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->ScaleX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->ScaleY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->PosX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->PosY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->SkewX = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->SkewY = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->Alpha = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->RotationAngle = DecodeProNode(pElem, QString(pElem->Value()));
        pElem = pElem->NextSiblingElement();
        re_m->Visible = DecodeProNode(pElem, QString(pElem->Value()));

        pElem = pElem->NextSiblingElement();
        while (pElem)
        {
            DisplayNode* d = DecodeDisNode(pElem, QString(pElem->Value()), path);
			if ( d != NULL)
				re_m->children.push_back(d);
			else
				return false;
            pElem = pElem->NextSiblingElement();
        }

        scene = re_s;
        movie = re_m;

		

        return true;

    }
    catch (exception e)
    {
		_errMsg = QString(e.what());
        return false;
    }
}
